home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 15 / BBS in a box XV-1.iso / Files / Internet / Misc / Uupc 3.1 sources.sit / uupc 3.1 sources Folder / (mail π) / mail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-26  |  12.5 KB  |  649 lines  |  [TEXT/KAHL]

  1. /*
  2.  * mail.c
  3.  */
  4.  
  5. #include <stdio.h>
  6. #ifdef THINK_C
  7. # include <console.h>
  8. #endif THINK_C
  9. #include "host.h"
  10.  
  11. #define exit return
  12.  
  13. FILE *freopen();
  14.  
  15. #define LSIZE    256
  16.  
  17. #include "mail.proto.h"
  18.  
  19. #include "mail.proto.h"
  20.  
  21. static char linebuf[LSIZE];
  22. static char resp[LSIZE];
  23.  
  24. static char mfilename[132];
  25.  
  26. struct ldesc {
  27.    int    delete;  /* status of this message */
  28.    long  adr;  /* address of From line */
  29.    long  Date;  /* address of Date: line */
  30.    long  subject; /* address of Subject: line */
  31.    long  from;  /* address of From: line */
  32.    long  size;  /* number of lines */
  33. };
  34.  
  35. struct ldesc letters[300];
  36.  
  37. int    letternum   = 0;
  38. char    thefilename[50];
  39.  
  40. char    tmailbox[64];
  41. char  tmailbag[64];
  42.  
  43.  
  44. FILE    *fmailbox;
  45. FILE  *rmailbox;
  46. FILE *fmailbag;
  47.  
  48. int error = 0;
  49. int modified;
  50.  
  51. extern SysEnvRec SysEnv;
  52.  
  53. int printonly;
  54.  
  55. int PageCount = 0;
  56.  
  57. mailmain(int argc, char **argv)
  58. {
  59.  
  60.  /* HOSTINIT;
  61.  loadenv(); */
  62.  
  63.  mkfilename( tmailbox, tempdir, "mailbox");
  64.  mkfilename( tmailbag, tempdir, "mailbag");
  65.  
  66.  unlink( tmailbox );
  67.  
  68.  if ( mailbox == (char *)NULL )
  69.   strcpy(mailbox,"???");
  70.  
  71.  if ( argc == 1 ||
  72.   ( argv[1][0] == '-' ) && ( argv[1][1] != 's' ))
  73.   showmail (argc, argv );
  74.  else
  75.   lmail (argc, argv );
  76.  
  77.  finis();
  78.  
  79. }
  80.  
  81. finis(void)
  82. {
  83.  if ( fmailbag != (FILE *)NULL) fclose( fmailbag );
  84.  unlink( tmailbox );
  85.  unlink( tmailbag );
  86.  exit( error );
  87. }
  88.  
  89. /* sendmail
  90.  send message n to "line"
  91. */
  92. sendmail(int n, char *line) {
  93.  char  *argv[50];
  94.  int  argc;
  95.  char buf[BUFSIZ];
  96.  long  bytes;
  97.  
  98.  /* open a temporary file */
  99.  fmailbag = FOPEN( tmailbag, "w", 'b' );
  100.  
  101.  /* copy nth message to mailbag file */
  102.  fseek( fmailbox, letters[ n ].adr, 0 );
  103.  bytes = letters[ n+1 ].adr - letters[ n ].adr;
  104.  
  105.  while( bytes > 0 && fgets( buf, BUFSIZ, fmailbox) ) {
  106.   fputs( buf, fmailbag  );
  107.   bytes -= strlen( buf );
  108.  }
  109.  
  110.  fclose( fmailbag );
  111.  
  112.  /* use mailbag as stdin to mail delivery */
  113.  fclose( stdin );
  114.  FILEMODE( 'b' );
  115.  if(freopen(tmailbag, "r", stdin) != (FILE *)NULL) {
  116.   argc = getargs(line, argv);
  117.   lmail(argc, argv);
  118.   fclose(stdin);
  119.  }
  120.  
  121. #ifdef MSDOS
  122.  FILEMODE( 't' );
  123.  freopen( CONSOLE, "r", stdin );
  124. #else
  125. # ifndef THINK_C
  126.  /* I don't know how this line following could ever
  127.   * produce the correct results - device is "modem" here
  128.   * not even /dev/tty for UNIX A. Shapiro 11/21/89
  129.   */
  130.  freopen( device, "r", stdin );
  131. # else THINK_C
  132.  /* opening a new console is NOT what is required here since
  133.   * the old stdout is still attached to the old console.
  134.   * Still if we get this far we'd better have something
  135.   * from which to issue the 'q'. (hope this code is never reached
  136.   * since the 'f' option was turned off.)
  137.   * A. Shapiro 11/21/89
  138.   */
  139.  freopenc((FILE *)NULL, stdin);
  140.  csetmode(C_ECHO, stdin);
  141. # endif THINK_C
  142. #endif
  143.  
  144.  /* get rid of mailbag */
  145.  unlink( tmailbag );
  146. }
  147.  
  148.  
  149. linvert(int i)
  150. {
  151.  return( letternum - i - 1 );
  152. }
  153.  
  154. showmail(int argc, char **argv) {
  155.  int flg, i, j, k, print;
  156.  char *p, *cp, *getnext();
  157.  long nextadr;
  158.  struct ldesc *letter;
  159.  
  160.  /* get mailbox file name */
  161.  mkfilename( mfilename, maildir, mailbox );
  162.  
  163.  /* parse arg's */
  164.  for (; argc > 1; argv++, argc--) {
  165.   if ( argv[1][0] == '-' ) {
  166.    if ( argv[1][1] == 'f' ) {
  167.     if ( argc >= 3) {
  168.      if ( argv[2][0] == '=' )
  169.       mkfilename( mfilename, maildir, &argv[2][1] );
  170.      else
  171.       strcpy( mfilename, argv[2] );
  172.      argv++;
  173.      argc--;
  174.     }
  175.  
  176.    }
  177.    else if(argv[1][1 ]== 'p')
  178.     printonly++;
  179.    else {
  180.     fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
  181.     finis();
  182.    }
  183.   }
  184.   else
  185.    break;
  186.  }
  187.  
  188.  /* open real mailbox file */
  189. #ifdef Upgrade
  190.  if((rmailbox=FOPEN(mfilename, "r", 't')) == (FILE *)NULL)
  191. #else Upgrade
  192.  if((rmailbox=FOPEN(mfilename, "r", 'b')) == (FILE *)NULL)
  193. #endif Upgrade
  194.  {
  195.   fprintf(stdout, "No mail in %s.\n", mfilename);
  196.   return;
  197.  }
  198.  
  199.  /* open up tmp mailbox file */
  200.    if (( fmailbox = FOPEN( tmailbox, "w", 'b' )) == (FILE *)NULL ) {
  201.   fprintf( stderr, "mail: cannot open %s for writing\n", tmailbox );
  202.   finis();
  203.  }
  204.  
  205.  /* copy real mailbox file to tmp mailbox file */
  206.  letternum = 0 ;
  207.  nextadr = 0;
  208.  while(fgets(linebuf, LSIZE, rmailbox) != (char *)NULL) {
  209.   fputs(linebuf, fmailbox);
  210.  
  211.   if ( strncmp( linebuf, "From ", 5 ) == SAME ) {
  212.    letter = &letters[letternum++];
  213.    letter->from =
  214.    letter->subject =
  215.    letter->Date = -1L;
  216.    letter->adr = nextadr;
  217.    letter->delete = FALSE;
  218.    letter->size = 0L;
  219.   }else if ( strncmp( linebuf, "Date: ", 6 ) == SAME )
  220.    letter->Date = nextadr;
  221.   else if ( strncmp( linebuf, "From: ", 6 ) == SAME )
  222.    letter->from = nextadr;
  223.   else if ( strncmp( linebuf, "Subject: ", 9 ) == SAME )
  224.    letter->subject = nextadr;
  225.  
  226.   letter->size += 1L;
  227.   nextadr += strlen( linebuf );
  228.  }
  229.  
  230.  letters[letternum].adr = nextadr;   /* last plus 1 */
  231.  
  232.  /* close mailbox files */
  233.  fclose( rmailbox );
  234.  fclose( fmailbox );
  235.  
  236.  fmailbox = FOPEN( tmailbox, "r", 'b' );
  237.  
  238.  modified = 0;
  239.  
  240.  if ( printonly ) {
  241.   j = letternum;
  242.   while ( j > 0 ) {
  243.    pager( j );
  244.    j--;
  245.   }
  246.  
  247.   return;
  248.      }
  249.  
  250.  
  251.  printsub( -1 );
  252.  
  253.  i = letternum - 1;
  254.  while ( TRUE ) {
  255.  
  256.   if ( i < 0 )
  257.    i = 0;
  258.   if ( i >= letternum)
  259.    i = letternum - 1;
  260.   j = linvert( i );
  261.  
  262.   fprintf( stdout, "%d ? ", linvert( i ) );
  263.   
  264.   if ( fgets( resp, LSIZE, stdin) == (char *)NULL )
  265.    break;
  266.  
  267.   switch ( resp[0] ) {
  268.   default:
  269.    fprintf(stderr, "usage\n");
  270.   case '?':
  271.    print = 0;
  272.    fprintf( stderr, "q\tquit\n" );
  273.    fprintf( stderr, "x\texit\tmailbox restored\n" );
  274.    fprintf( stderr, "p\tprint message\n" );
  275.    fprintf( stderr, "s[file]\tsave message to a file (default =mbox)\n" );
  276.    fprintf( stderr, "w[file]\tsave message to a file (default =mbox) without headers\n" );
  277.    fprintf( stderr, "-\tprint last message\n" );
  278.    fprintf( stderr, "d\tdelete current message\n" );
  279.    fprintf( stderr, "+\tnext message (no delete)\n" );
  280.    fprintf( stderr, "f user\tforward current message to user\n" );
  281.    fprintf( stderr, "m user\tmail a message to user\n" );
  282.    fprintf( stderr, "g num\t set current message\n" );
  283.    break;
  284.   case '+':
  285.   case 'n':
  286.    i-- ;
  287.    break;
  288.   case 'g':
  289.    i = linvert( atoi( resp+2 ) );
  290.    break;
  291.   case '0':
  292.   case '1':
  293.   case '2':
  294.   case '3':
  295.   case '4':
  296.   case '5':
  297.   case '6':
  298.   case '7':
  299.   case '8':
  300.   case '9':
  301.    i = linvert( atoi( resp ) );
  302.    break;
  303.  
  304.   case 'x':
  305.    modified = 0;
  306.   case 'q':
  307.    goto donep;
  308.   case '\n':
  309.   case 'p':
  310.    pager( j );
  311.    break;
  312.   case '^':
  313.   case '-':
  314.    i++;
  315.    break;
  316.   case 'y':
  317.   case 'w':
  318.   case 's':
  319.    flg = 0;
  320.    if (resp[1] != '\n' && resp[1] != ' ') {
  321.     printf("illegal\n");
  322.     flg++;
  323.     print = 0;
  324.     continue;
  325.    }
  326.    if (strlen( resp ) == 1)
  327.     strcat( resp, " =mbox" );
  328.    for (p = resp+1; (p = getnext( &cp, p )) != (char *)NULL; ) {
  329.       if ( *cp == '=' )
  330.                        mkfilename( thefilename, maildir, ++cp );
  331.       else
  332.          strcpy( thefilename, cp );
  333.       fprintf( stderr, "%s to %s\n",
  334.         (resp[0] == 's') ? "Appending":"Writing", thefilename );
  335.       if (( fmailbag=FOPEN( thefilename, "a", 't' )) == (FILE *)NULL ) {
  336.          fprintf( stdout, "mail: cannot append to %s\n",
  337.                   thefilename );
  338.       flg++;
  339.       continue;
  340.       }
  341.       copymsg( j, fmailbag, resp[0]=='w' );
  342.       fclose( fmailbag );
  343.    }
  344.    if (flg)
  345.     print = 0;
  346.    else {
  347.     letters[j].delete = TRUE;
  348.     modified++;
  349.     i--;
  350.    }
  351.    break;
  352.   case 'm':
  353.    fprintf( stderr, "mail command not implemented yet!\n" );
  354.    break;
  355.   case 'f':
  356.    fprintf( stderr, "forward command not implemented yet!\n" );
  357.    break;
  358.    
  359.    /* NOTREACHED */
  360.    /* the problem with this code seems to be with closure
  361.     * of stdin to redirect input from mailbag. I would suggest
  362.     * recoding this program to allow an extra parameter to
  363.     * lmail, namely <stream> so that stdin is not futzed
  364.     * with. This will (of course) mess with the beautifully
  365.     * convoluted nature of this program and make it intelligible
  366.     * but I guess we can't have everything
  367.     * 8-). A. Shapiro 11/21/89
  368.     */
  369.    flg = 0;
  370.    if (resp[1] == '\n' || resp[1] == '\0') {
  371.     i++;
  372.     continue;
  373.    }
  374.    if (resp[1] != ' ') {
  375.     printf( "invalid command\n" );
  376.     flg++;
  377.     print = 0;
  378.     continue;
  379.    }
  380.  
  381.    sendmail(j, p);
  382.  
  383.    if (flg)
  384.     print = 0;
  385.    else {
  386.     letters[j].delete = TRUE;
  387.     modified++;
  388.     i++;
  389.    }
  390.    break;
  391.  
  392.   case 'd':
  393.    letters[j].delete = TRUE;
  394.    modified++;
  395.    i--;
  396.    if (resp[1] == 'q')
  397.     goto donep;
  398.    break;
  399.  
  400.   case 'h':
  401.    printsub( -1 );
  402.    break;
  403.  
  404.   case 'H':
  405.    printsub( i );
  406.    break;
  407.  
  408.   }
  409.  
  410.  }
  411.  donep:
  412.  if ( modified )
  413.   copyback();
  414. }
  415.  
  416. readaline(long adr, char *line)
  417. {
  418.  char  buf[132];
  419.  char *cp;
  420.  
  421.  *line = '\0';
  422.  if ( adr != -1L )
  423.   if ( fseek( fmailbox, adr, 0 ) == 0 )
  424.    if ( fgets( buf, 132, fmailbox ) != (char *)NULL )
  425.     strcpy( line, buf );
  426.  
  427.  if ( (cp = index( line, '\n' ) ) != (char *) NULL)
  428.   *cp = '\0';
  429. }
  430.  
  431.  
  432. /*
  433. returnaddress()
  434. {
  435.  readaline( lp->from, linebuf );
  436.  if (
  437.   ( i = index( linebuf, '<' )) != 0 &&
  438.   ( k = index( linebuf, '>')) != 0 &&
  439.   ( k > i )
  440.   )
  441.  {
  442.   k -= i;
  443.   strncpy( from, linebuf[i], k );
  444.   from[k] = '\0';
  445.  }
  446.  else {
  447.  
  448.  
  449.  }
  450. }
  451. */
  452.  
  453. printsub(int K)
  454. {
  455.  struct ldesc *ld;
  456.  int  j;
  457.  char from[132], subject[132], Date[132], line[132];
  458.  register char *sp, *dp, *lp, *tp;
  459.  int k, mink, maxk;
  460.  
  461.  pagereset();
  462.  
  463.  if ( K == -1 ) {
  464.   maxk = letternum -1;
  465.   mink = 0;
  466.  }
  467.  else
  468.   maxk = mink = K;
  469.  
  470.  for ( k = maxk ; k >= mink ; k-- ) {
  471.  
  472.   j = linvert( k );
  473.   ld = & letters[ j /*k*/];
  474.  
  475.    (void)strcpy(from, "unknown"); /* default to "unknown" */
  476.   readaline( ld->from, line );
  477.   if ( strlen( line ) > 0 ) {
  478.    /* Assume From: mailbox@site.domain */
  479.    /* get first usable stuff after From: */
  480.    sp = index( line, ':' ) + 1;
  481.  
  482.    /* do we have From: mailbox@site.domain ( Proper Name ) */
  483.    if ( ( ( tp = index( line, '(' )) != (char *) NULL &&
  484.      ( lp = index( line, ')')) != (char *) NULL  ) )
  485.     sp = ++tp;
  486.    /* or we may have From: Proper Name < mailbox@site.domain > */
  487.    else
  488.     lp = index( line, '<');
  489.  
  490.    if ( *lp == '<' || *lp == ')' )
  491.     --lp;
  492.  
  493.    /* if we didn't get either of the last two, just grab line */
  494.    if ( lp < sp || lp == (char *) NULL )
  495.     lp = line + strlen( line ) - 1;
  496.  
  497.    /*debugMsg("\PCheck isspace *sp");*/
  498.    while ( isspace( *sp ) ) sp++;
  499.  
  500.    /*debugMsg("\PCheck isspace *lp");*/
  501.    while ( isspace( *lp ) ) lp--;
  502.  
  503.    dp = from;
  504.    while ( sp <= lp ) *dp++ = *sp++;
  505.    *dp = '\0';
  506.   }
  507.  
  508.   /* Date: Wed May 13 23:59:53 1987 */
  509.    *Date = '\0'; /* default Date to null */
  510.   readaline( ld->Date, Date );
  511.   if ( strlen( Date ) > 0 ) {
  512.    sscanf( Date, "%*s %*s %s %s", line, subject );
  513.    sprintf( Date, "%s %s", line, subject );
  514.   }
  515.  
  516.   strcpy( subject, "--- no subject ---" );
  517.   readaline( ld->subject, line );
  518.   if ( strlen( line ) > 0 ) {
  519.    sp = line;
  520.    while ( !isspace( *sp ) ) sp++;
  521.    while ( isspace( *sp ) ) sp++;
  522.    strcpy( subject, sp );
  523.    }
  524.  
  525.   from[20] = '\0';
  526.   Date[6] = '\0';
  527.   subject[35] = '\0';
  528.  
  529.   sprintf( line, "%3d  %6s  %20s %35s (%6d)\n",
  530.       j, Date, from, subject, ld->size );
  531.   if ( pageline( line ) == TRUE )
  532.    break;
  533.  }
  534. }
  535.  
  536.  
  537. copyback(void)
  538. {
  539.  register i, n, c;
  540.  int new = 0;
  541.  
  542.  if (( fmailbag = FOPEN( mfilename, "w", 'b' )) == (FILE *)NULL ) {
  543.   fprintf (stderr, "mail: can't rewrite %s\n", mfilename );
  544.   finis();
  545.  }
  546.  n = 0;
  547.  for ( i = 0; i < letternum; i++ )
  548.   if ( letters[i].delete == FALSE ) {
  549.    copymsg( i, fmailbag, FALSE );
  550.    n++;
  551.   }
  552.  fclose (fmailbag );
  553. }
  554.  
  555.  
  556. /* copy a message
  557.    if noheaders true, don't copy header lines
  558. */
  559. copymsg(int n, FILE *f, int noheaders)
  560. {
  561.  long  bytes;
  562.  char buf[BUFSIZ];
  563.  
  564.  fseek( fmailbox, letters[n].adr, 0 );
  565.  bytes = letters[n+1].adr - letters[n].adr;
  566.  
  567.  while ( bytes > 0 && fgets( buf, BUFSIZ, fmailbox ) != (char *)NULL ) {
  568.   bytes -= strlen( buf );
  569.  
  570.   /* write line */
  571.   if ( !noheaders  )
  572.    fputs( buf, f );
  573.  
  574.   /* reset header */
  575.   if ( noheaders  && strcmp( buf, "\n") == SAME )
  576.    noheaders  = FALSE;
  577.  
  578.  }
  579. }
  580.  
  581. pager(int n)
  582. {
  583.  long  bytes;
  584.  char buf[BUFSIZ];
  585.  
  586.  fseek( fmailbox, letters[n].adr, 0 );
  587.  bytes = letters[n+1].adr - letters[n].adr;
  588.  
  589.  pagereset();
  590.  while ( bytes > 0 && fgets( buf, BUFSIZ, fmailbox ) != (char *)NULL ) {
  591.   bytes -= strlen( buf );
  592.   if ( pageline( buf ) == TRUE )
  593.    break;
  594.  }
  595.  
  596.  pageline( "\n" );
  597. }
  598.  
  599. pagereset(void)
  600. {
  601.  PageCount = 0;
  602. }
  603.  
  604. pageline(char *s)
  605. {
  606.  char c;
  607.  
  608.  fputs( s, stdout );
  609.  if ( ++PageCount > 23 ) {
  610.   PageCount = 0;
  611.   c = get_one();
  612.   switch( c ) {
  613.   case 'q':
  614.   case 'Q':
  615.   case '\003':
  616.   case 'x':
  617.   case 'X':
  618.    return( TRUE );
  619.   }
  620.  }
  621.  return( FALSE );
  622. }
  623.  
  624. char *getnext(char **s, char *p)
  625. {
  626.  *s = (char *)NULL;
  627.  while ( *p == ' ' || *p == '\t' )
  628.   p++;
  629.  if ( *p == '\n' || *p == '\0' )
  630.   return( (char *)NULL );
  631.  *s = p;
  632.  while ( *p != ' ' && *p != '\t' && *p != '\n' && *p != '\0' )
  633.   *p++;
  634.  if ( *p != '\0' )
  635.   *p++ = '\0';
  636.  return(p);
  637. }
  638.  
  639. #ifdef MULTIFINDER
  640.  
  641. int Check_Events(long Sleep_Time)
  642. {
  643.      EventRecord Cur_Event;
  644.     (void) WaitNextEvent(updateMask, &Cur_Event, 0, (RgnHandle) NULL);
  645.     SystemTask();
  646. }
  647.  
  648. #endif
  649.